home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 February: Tool Chest / Apple Developer CD Series Tool Chest February 1996 (Apple Computer)(1996).iso / Tool Chest / Text / WASTE / WASTE 1.2a2 / WEObjects.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-10-12  |  9.5 KB  |  369 lines  |  [TEXT/CWIE]

  1. /*
  2.  *    WEObjects.c
  3.  *
  4.  *    WASTE PROJECT
  5.  *  Embedded Objects
  6.  *
  7.  *  Copyright (c) 1993-1995 Marco Piovanelli
  8.  *    All Rights Reserved
  9.  *
  10.  *  C port by Dan Crevier
  11.  *
  12.  */
  13.  
  14.  
  15. #include "WASTEIntf.h"
  16.  
  17. #if WASTE_OBJECTS
  18.  
  19. // static variables
  20.  
  21. static WEOHTableHandle _weGlobalObjectHandlerTable;
  22.  
  23. pascal FlavorType WEGetObjectType(WEObjectDescHandle hObjectDesc)
  24. {
  25.     return (*hObjectDesc)->objectType;
  26. } // WEGetObjectType
  27.  
  28. pascal Handle WEGetObjectDataHandle(WEObjectDescHandle hObjectDesc)
  29. {
  30.     return (*hObjectDesc)->objectDataHandle;
  31. } // WEGetObjectDataHandle
  32.  
  33. pascal Point WEGetObjectSize(WEObjectDescHandle hObjectDesc)
  34. {
  35.     return (*hObjectDesc)->objectSize;
  36. } // WEGetObjectSize
  37.  
  38. pascal WEHandle WEGetObjectOwner(WEObjectDescHandle hObjectDesc)
  39. {
  40.     return (*hObjectDesc)->objectOwner;
  41. } // WEGetObjectOwner
  42.  
  43. pascal long WEGetObjectRefCon(WEObjectDescHandle hObjectDesc)
  44. {
  45.     return (*hObjectDesc)->objectRefCon;
  46. } // WEGetObjectRefCon
  47.  
  48. pascal void WESetObjectRefCon(WEObjectDescHandle hObjectDesc, long refCon)
  49. {
  50.     (*hObjectDesc)->objectRefCon = refCon;
  51. } // WESetObjectRefCon
  52.  
  53. pascal long _WELookupObjectType(FlavorType objectType, WEOHTableHandle hTable)
  54. {
  55.     // look for a WEOHTableElement record for the specified object kind
  56.     // in the given object handler table
  57.  
  58.     long nEntries, index;
  59.     WEOHTablePtr pTable;
  60.  
  61.     // do nothing if the Object Handler Table has not been inited yet
  62.     if (hTable == NULL)
  63.         return kUnknownObjectType;
  64.  
  65.     // calculate entry count
  66.     nEntries = GetHandleSize((Handle) hTable) / sizeof(WEOHTableElement);
  67.  
  68.     // scan the Object Handler Table looking for a type match
  69.     pTable = *hTable;
  70.     for ( index = 0; index < nEntries; index++ )
  71.     {
  72.         if (pTable->objectType == objectType) 
  73.             return index;
  74.         pTable++;
  75.     }
  76.     
  77.     return kUnknownObjectType;
  78. } // _WELookupObjectType
  79.  
  80. pascal OSErr _WEGetIndObjectType(long index, FlavorType *objectType, WEHandle hWE)
  81. {
  82.     WEOHTableHandle hTable;
  83.     long nEntries;
  84.  
  85.     *objectType = 0L;
  86.  
  87.     // index must be non-negative
  88.     if (index < 0)
  89.         return weUnknownObjectTypeErr;
  90.     
  91.     // calculate number of entries in the instance-specific handler table
  92.     nEntries = 0;
  93.     hTable = (*hWE)->hObjectHandlerTable;
  94.     if (hTable != NULL)
  95.         nEntries = GetHandleSize((Handle) hTable) / sizeof(WEOHTableElement);
  96.  
  97.     // low indices refer to the instance-specific handler table
  98.     if (index < nEntries)
  99.     {
  100.         *objectType = (*hTable)[index].objectType;
  101.         return noErr;
  102.     }
  103.     // indices above that refer to the global handler table
  104.     index -= nEntries;
  105.  
  106.     // calculate number of entries in the global handler table
  107.     nEntries = 0;
  108.     hTable = _weGlobalObjectHandlerTable;
  109.     if (hTable != NULL)
  110.         nEntries = GetHandleSize((Handle) hTable) / sizeof(WEOHTableElement);
  111.  
  112.     // return an error code if index is too large
  113.     if (index >= nEntries)
  114.         return weUnknownObjectTypeErr;
  115.  
  116.     *objectType = (*hTable)[index].objectType;
  117.     
  118.     return noErr;
  119. } // _WEGetIndObjectType
  120.  
  121. pascal OSErr _WENewObject(FlavorType objectType, Handle objectDataHandle, WEHandle hWE,
  122.                     WEObjectDescHandle *hObjectDesc)
  123. {
  124.     WEObjectDescPtr pDesc;
  125.     WEOHTableHandle hTable;
  126.     long index;
  127.     OSErr err;
  128.     
  129.     *hObjectDesc = NULL;
  130.  
  131.     // first look up the specified object type in the instance-specific handler table
  132.     hTable = (*hWE)->hObjectHandlerTable;
  133.     if ((index = _WELookupObjectType(objectType, hTable)) == kUnknownObjectType)
  134.     {
  135.         // no match: try with the global handler table
  136.         hTable = _weGlobalObjectHandlerTable;
  137.         if ((index = _WELookupObjectType(objectType, hTable)) == kUnknownObjectType)
  138.             hTable = NULL;
  139.     }
  140.     
  141.     // create a new relocatable block to hold the object descriptor
  142.     if ((err = _WEAllocate(sizeof(WEObjectDesc), kAllocClear, (Handle *)hObjectDesc)) != noErr)
  143.         return err;
  144.  
  145.     // lock it down
  146.     HLock((Handle) *hObjectDesc);
  147.     pDesc = (WEObjectDescPtr) **hObjectDesc;
  148.  
  149.     // fill in the object descriptor
  150.     pDesc->objectType = objectType;
  151.     pDesc->objectDataHandle = objectDataHandle;
  152.     pDesc->objectSize.v = kDefaultObjectHeight;
  153.     pDesc->objectSize.h = kDefaultObjectWidth;
  154.     pDesc->objectTable = hTable;
  155.     pDesc->objectIndex = index;
  156.     pDesc->objectOwner = hWE;
  157.  
  158.     if (hTable != NULL) 
  159.     {
  160.         WENewObjectUPP newHandler = (*hTable)[index].newHandler;
  161.  
  162.         // call the new handler, if any
  163.         if (newHandler != NULL) 
  164.         {
  165.             if ((err = CallWENewObjectProc(&pDesc->objectSize, *hObjectDesc, newHandler)) != noErr)
  166.             {
  167.                 _WEForgetHandle((Handle *) hObjectDesc);
  168.                 return err;
  169.             }
  170.         }
  171.     }
  172.     
  173.     // unlock the object descriptor
  174.     HUnlock((Handle) *hObjectDesc);
  175.  
  176.     // clear result code
  177.     return noErr;
  178. } // _WENewObject
  179.  
  180. pascal OSErr _WEFreeObject(WEObjectDescHandle hObjectDesc)
  181. {
  182.     WEObjectDescPtr pDesc;
  183.     OSErr err = noErr;
  184.  
  185.     // sanity check: do nothing if we have a null descriptor handle
  186.     if (hObjectDesc == NULL) 
  187.         return nilHandleErr;
  188.  
  189.     // lock the descriptor record
  190.     HLock((Handle)hObjectDesc);
  191.     pDesc = *hObjectDesc;
  192.  
  193.     if (pDesc->objectTable != NULL) 
  194.     {
  195.         WEDisposeObjectUPP freeHandler = (*pDesc->objectTable)[pDesc->objectIndex].freeHandler;
  196.  
  197.         // call the dispose handler, if any
  198.         if (freeHandler != NULL) 
  199.         {
  200.             err = CallWEDisposeObjectProc(hObjectDesc, freeHandler);
  201.             pDesc->objectDataHandle = NULL;
  202.         }
  203.     }
  204.     
  205.     // if object kind is unknown or there's no custom dispose handler, use DisposeHandle
  206.     _WEForgetHandle(&pDesc->objectDataHandle);
  207.  
  208.     // finally, dispose of the object descriptor itself
  209.     DisposeHandle((Handle)hObjectDesc);
  210.  
  211.     return err;
  212. } // _WEFreeObject
  213.  
  214. pascal OSErr _WEDrawObject(WEObjectDescHandle hObjectDesc)
  215. {
  216.     WEObjectDescPtr pDesc;
  217.     Rect destRect;
  218.     PenState state;
  219.     Boolean saveDescLock;
  220.     OSErr err = noErr;
  221.     
  222.     // lock the object descriptor
  223.     saveDescLock = _WESetHandleLock((Handle)hObjectDesc, true);
  224.     pDesc = *hObjectDesc;
  225.  
  226.     // get current pen state
  227.     // state.pnLoc has already been set to the bottom left of the rectangle to draw
  228.     GetPenState(&state);
  229.  
  230.     // calculate the new pen position
  231.     state.pnLoc.h += pDesc->objectSize.h;
  232.  
  233.     // calculate the destination rectangle
  234.     *(long *)(&topLeft(destRect)) = DeltaPoint(state.pnLoc, pDesc->objectSize);
  235.     botRight(destRect) = state.pnLoc;
  236.  
  237.     if (pDesc->objectTable != NULL) 
  238.     {
  239.         WEDrawObjectUPP drawHandler = (*pDesc->objectTable)[pDesc->objectIndex].drawHandler;
  240.  
  241.         // call the drawing handler, if any
  242.         if (drawHandler != NULL) 
  243.             err = CallWEDrawObjectProc(&destRect, hObjectDesc, drawHandler);
  244.     }
  245.     else
  246.     {
  247.         // if this object kind was not registered, draw an empty frame
  248.         PenNormal();
  249.         FrameRect(&destRect);
  250.     }
  251.     
  252.     // restore original pen state, advancing the pen position by the object width
  253.     SetPenState(&state);
  254.  
  255.     // unlock the object descriptor
  256.     _WESetHandleLock((Handle)hObjectDesc, saveDescLock);
  257.  
  258.     return err;
  259. } // _WEDrawObject
  260.  
  261. pascal Boolean _WEClickObject(Point hitPt, EventModifiers modifiers, unsigned long clickTime,
  262.                                 WEObjectDescHandle hObjectDesc)
  263. {
  264.     WEObjectDescPtr pDesc;
  265.     Boolean saveDescLock;
  266.     Boolean clickHandled = false;
  267.  
  268.     // lock the object descriptor
  269.     saveDescLock = _WESetHandleLock((Handle)hObjectDesc, true);
  270.     pDesc = *hObjectDesc;
  271.  
  272.     if (pDesc->objectTable != NULL)
  273.     {
  274.         WEClickObjectUPP clickHandler = (*pDesc->objectTable)[pDesc->objectIndex].clickHandler;
  275.  
  276.         // call the click handler, if any
  277.         if (clickHandler != NULL)
  278.             clickHandled = CallWEClickObjectProc(hitPt, modifiers, clickTime, hObjectDesc, clickHandler);
  279.     }
  280.  
  281.     // unlock the object descriptor
  282.     _WESetHandleLock((Handle)hObjectDesc, saveDescLock);
  283.     
  284.     return clickHandled;
  285. } // _WEClickObject
  286.  
  287. pascal OSErr _WEStreamObject(short destKind, FlavorType *theType,
  288.                 Handle *theData, Boolean *canDisposeData, WEObjectDescHandle hObjectDesc)
  289. {
  290.     WEObjectDescPtr pDesc;
  291.     Boolean saveDescLock;
  292.     OSErr err = weNotHandledErr;
  293.     
  294.     *canDisposeData = true;
  295.  
  296.     // lock the object descriptor
  297.     saveDescLock = _WESetHandleLock((Handle)hObjectDesc, true);
  298.     pDesc = *hObjectDesc;
  299.  
  300.     if (pDesc->objectTable != NULL)
  301.     {
  302.         WEStreamObjectUPP streamHandler = (*pDesc->objectTable)[pDesc->objectIndex].streamHandler;
  303.  
  304.         // call the stream handler, if any
  305.         if (streamHandler != NULL)
  306.             err = CallWEStreamObjectProc(destKind, theType, *theData, hObjectDesc, streamHandler);
  307.     }
  308.     
  309.     if (err == weNotHandledErr)
  310.     {
  311.         // default streaming behavior
  312.         _WEForgetHandle(theData);
  313.         *canDisposeData = false;
  314.         *theType = pDesc->objectType;
  315.         *theData = pDesc->objectDataHandle;
  316.         err = noErr;
  317.     }
  318.     
  319.     // unlock the object descriptor
  320.     _WESetHandleLock((Handle) hObjectDesc, saveDescLock);
  321.     
  322.     return err;
  323. } // _WEStreamObject
  324.  
  325. pascal OSErr WEInstallObjectHandler(FlavorType objectType, WESelector handlerSelector,
  326.                 UniversalProcPtr handler, WEHandle hWE)
  327. {
  328.     WEOHTableHandle hTable;
  329.     long index;
  330.     WEOHTableElement element;
  331.     OSErr err;
  332.  
  333.     // if hWE is NULL, install the handler in the global handler table,
  334.     // otherwise install the handler in the instance-specific handler table
  335.     if (hWE == NULL)
  336.         hTable = _weGlobalObjectHandlerTable;
  337.     else
  338.         hTable = (*hWE)->hObjectHandlerTable;
  339.  
  340.     // create the handler table, if it doesn't exist
  341.     if (hTable == NULL) 
  342.     {
  343.         hTable = (WEOHTableHandle) NewHandle(0);
  344.         if ((err = MemError()) != noErr) 
  345.             return err;
  346.         if (hWE == NULL)
  347.             _weGlobalObjectHandlerTable = hTable;
  348.         else
  349.             (*hWE)->hObjectHandlerTable = hTable;
  350.     }
  351.  
  352.     // look for the entry corresponding to the specified object type
  353.     if ((index = _WELookupObjectType(objectType, hTable)) == kUnknownObjectType) 
  354.     {
  355.         BLOCK_CLR(element);
  356.         element.objectType = objectType;
  357.  
  358.         // previously unknown object type: append a new entry at the end of the handler table
  359.         index = GetHandleSize((Handle) hTable) / sizeof(WEOHTableElement);
  360.         if ((err = _WEInsertBlock((Handle) hTable, (const void *) &element, sizeof(element), index * sizeof(element))) != noErr)
  361.             return err;
  362.     }
  363.     
  364.     // install the handler
  365.     return _WESetHandler(handlerSelector, (long *) &handler, (void *) (*hTable + index));
  366.  
  367. } // WEInstallObjectHandler
  368.  
  369. #endif  // WASTE_OBJECTS